﻿using Infrastructure.Utility.Core.CommonUtility;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;

namespace Infrastructure.Utility.Core.EncryptAES256
{
    public static class StaticAes256Helper
    {
        private static readonly string _encryptKey = "20fIjBkxcYUeOifaGzZ5HtUYYhh9XjJBfyC2s/t671w=";//不可修改
        private static readonly string _encryptIv = "N0wgg6Tzo5vQS+jX6V7K1w==";//不可修改
        public static readonly string EncryptSignatureCode = "【*E*N*C*R*Y*P*T*】";//加密特征码
        public static readonly string EncryptExceptionCode = "【*E*X*C*E*P*T*】";//加密例外码（此码开头的字符串，均去码后返回）
        private static byte[] _aesKey = Convert.FromBase64String(_encryptKey);
        private static byte[] _aesIv = Convert.FromBase64String(_encryptIv);

        private static RijndaelManaged rDel = new RijndaelManaged
        {
            Key = _aesKey,
            IV = _aesIv,
            Mode = CipherMode.CBC,
            Padding = PaddingMode.PKCS7
        };

        #region 加密算法
        /// <summary>
        /// 加密
        /// 加密字符串，并添加特征码
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string Encrypt(this string input)
        {
            try
            {
                //1、空字符串，直接返回空
                if (string.IsNullOrWhiteSpace(input))
                {
                    return string.Empty;
                }

                //2、例外码开头的，去码后返回（返回原文）
                if (!string.IsNullOrWhiteSpace(EncryptExceptionCode) && input.StartsWith(EncryptExceptionCode))
                {
                    return input.Substring(EncryptExceptionCode.Length);
                }

                //3、特征码开头的，直接返回（不重复加密）
                if (!string.IsNullOrWhiteSpace(EncryptSignatureCode) && input.StartsWith(EncryptSignatureCode))
                {
                    return input;
                }

                //4、默认AES256加密，并加上特征码
                var encryptStr = input.EncryptString();

                return $"{EncryptSignatureCode}{encryptStr}";
            }
            catch
            { }
            return input;
        }

        private static string EncryptString(this string input)
        {
            try
            {
                using var encryptor = rDel.CreateEncryptor();
                var toEncryptArray = Encoding.UTF8.GetBytes(input);
                var resultArray = encryptor.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                var encryptStr = Convert.ToBase64String(resultArray, 0, resultArray.Length);
                return encryptStr;
            }
            catch (Exception)
            {
                return $"加密失败:{input}";
            }
        }
        #endregion

        #region 解密算法
        /// <summary>
        /// 解密
        /// 去特性后，解密字符串
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string Decrypt(this string input)
        {
            try
            {
                //1、空字符串，直接返回空
                if (string.IsNullOrWhiteSpace(input))
                {
                    return string.Empty;
                }

                //2、例外码【*E*X*C*E*P*T*】开头的，去码后返回（返回原文）
                if (!string.IsNullOrWhiteSpace(EncryptExceptionCode) && input.StartsWith(EncryptExceptionCode))
                {
                    return input.Substring(EncryptExceptionCode.Length);
                }

                //3、以特征码【*E*N*C*R*Y*P*T*】开头的字符串，解密返回，反之返回原文
                if (input.StartsWith(EncryptSignatureCode))
                    return input.Replace(EncryptSignatureCode, string.Empty).DecryptString();
                else
                    return input;
            }
            catch 
            {
            }

            return input;
        }

        private static string DecryptString(this string input)
        {
            try
            {
                using var decryptor = rDel.CreateDecryptor();
                byte[] toEncryptArray = Convert.FromBase64String(input);
                byte[] resultArray = decryptor.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
                return UTF8Encoding.UTF8.GetString(resultArray);
            }
            catch (Exception)
            {
                return $"解密失败:{input}";
            }
        }
        #endregion

        #region 扩展方法（加密后返回明文+密文）
        /// <summary>
        /// 加密字符串，并返回明文+密文列表
        /// </summary>
        /// <param name="input"></param>
        /// <param name="addEncryptExceptionCode"></param>
        /// <returns></returns>
        public static List<string> EncryptWithOrigin(this string input, bool addEncryptExceptionCode = true)
        {
            var result = new List<string>();

            if (string.IsNullOrWhiteSpace(input))
            {
                return result;
            }

            //原文
            result.Add(input);
            //原文+例外码
            if (addEncryptExceptionCode)
            {
                result.Add(EncryptExceptionCode + input);
            }
            //密文
            result.Add(input.Encrypt());

            return result;
        }

        /// <summary>
        /// 加密字符串列表，并返回明文+密文列表
        /// </summary>
        /// <param name="input"></param>
        /// <param name="addEncryptExceptionCode"></param>
        /// <returns></returns>
        public static List<string> EncryptWithOrigin(this List<string> input, bool addEncryptExceptionCode = true)
        {
            var result = new List<string>();

            foreach (var mobile in input)
            {
                result.AddRange(mobile.EncryptWithOrigin(addEncryptExceptionCode));
            }

            return result;
        }
        #endregion


        #region 加密手机号逻辑由网关1.0  迁移到 业务内部，因为网关2.0 不支持处理

        /// <summary>
        /// 网关加密手机号
        /// </summary>
        /// <param name="mobile"></param>
        /// <returns>返回网关加密后的密文（供查看手机号和外呼解密使用）</returns>
        public static string GateWayEncryptMobile(string mobile)
        {
            if (string.IsNullOrWhiteSpace(mobile))
            {
                return mobile;
            }
            //yl2019#$ ----->  yl2019#$00000000
            //网关1.0 写死的key
            var key = "yl2019#$00000000";
            using (var rijndaelCipher = Aes.Create("AesManaged"))
            {
                rijndaelCipher.Mode = CipherMode.ECB;
                rijndaelCipher.Padding = PaddingMode.PKCS7;
                rijndaelCipher.KeySize = 128;
                rijndaelCipher.BlockSize = 128;
                byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
                byte[] keyBytes = new byte[16];
                int len = pwdBytes.Length;
                if (len > keyBytes.Length)
                    len = keyBytes.Length;
                Array.Copy(pwdBytes, keyBytes, len);
                rijndaelCipher.Key = keyBytes;
                rijndaelCipher.IV = keyBytes;
                using (ICryptoTransform transform = rijndaelCipher.CreateEncryptor())
                {
                    byte[] plainText = Encoding.UTF8.GetBytes(mobile);
                    byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length);
                    return Convert.ToBase64String(cipherBytes);
                }

            }

        }
        #endregion
    }
}